package com.briup.srms.base.config;

import com.briup.srms.base.bean.BasePrivilege;
import com.briup.srms.base.service.IBasePrivilegeService;
import com.briup.srms.base.utils.RedisUtil;
import com.jacky.base.utils.JwtTokenUtil;
import com.jacky.base.utils.PermissionException;
import com.jacky.base.utils.UnAuthorizedException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @description:
 * @author: charles
 * @create: 2020-11-18 21:02
 **/

public class JwtInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private IBasePrivilegeService basePrivilegeService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("interceptor......");
        // 如果是options请求，直接返回true，不进行拦截
        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        // 1. 获取请求头信息authorization信息
        final String token = request.getHeader(JwtTokenUtil.AUTH_HEADER_KEY);
        if (StringUtils.isEmpty(token)) {
            throw new UnAuthorizedException("用户还未登录");
        }

        // 2. 验证token是否有效--无效已做异常抛出，由全局异常处理后返回对应信息
        JwtTokenUtil.parseJWT(token, JwtTokenUtil.base64Secret);

        //3. 验证权限，通过token获取用户id，通过用户id获取权限，这里可以使用redis将用户信息维护在缓存中，减少与数据库交互次数
        long id = Long.parseLong(JwtTokenUtil.getUserId(token, JwtTokenUtil.base64Secret));
        this.auth(id, request.getServletPath());

        return true;
    }

    // 判断权限
    @SuppressWarnings("unused")
    private boolean auth(long userId, String path) {

        // 从Redis中查询权限树是否被缓存过
        Object obj = redisUtil.getPrivilegeTree(userId);
        List<BasePrivilege> privileges = null;

        if (obj == null) {
            // 没有被缓存，从数据库中查询
            privileges = basePrivilegeService.findByUserId(userId);
            // 存入Redis
            redisUtil.cachePrivilegeTree(userId, privileges);
        } else {
            privileges = (List<BasePrivilege>) obj;
        }
        // article/findAll
        // 判断权限树中是否存在用户当前要访问的路径
        System.out.println("path:" + path);
        for (BasePrivilege p : privileges) {
            System.out.println(p.getRoute());
            // 匹配
            if (p.getRoute().matches(path)) {
                return true;
            }
        }
        throw new PermissionException("权限不足");
    }
}
